﻿namespace Atomic.Mvc
{
    using System;
    using System.Reflection;

    using Autofac;

    /// <summary>
    /// 默认 IoC 容器。
    /// </summary>
    public class DefaultAtomicContainer : IAtomicContainer
    {
        /// <summary>
        /// 容器。
        /// </summary>
        private readonly IContainer _container = null;

        /// <summary>
        /// 默认 IoC 容器。
        /// </summary>
        /// <param name="container">容器。</param>
        public DefaultAtomicContainer(IContainer container)
        {
            this._container = container;
        }

        /// <summary>
        /// 注册类型到容器。
        /// </summary>
        /// <param name="serviceType">类型。</param>
        public void RegisterType(Type serviceType)
        {
            ThrowIfNotInitialized();

            ContainerBuilder containerBuilder = new ContainerBuilder();

            containerBuilder.RegisterType(serviceType);

            containerBuilder.Update(_container);
        }

        /// <summary>
        /// 注册类型到容器。
        /// </summary>
        /// <typeparam name="TSource">类型。</typeparam>
        public void RegisterType<TSource>()
        {
            ThrowIfNotInitialized();

            ContainerBuilder containerBuilder = new ContainerBuilder();

            containerBuilder.RegisterType<TSource>();

            containerBuilder.Update(_container);
        }

        /// <summary>
        /// 注册类型到容器。
        /// </summary>
        /// <typeparam name="TFrom">父类型</typeparam>
        /// <param name="serviceType">实现类型。</param>
        public void RegisterType<TFrom>(Type serviceType)
        {
            ThrowIfNotInitialized();

            ContainerBuilder containerBuilder = new ContainerBuilder();

            containerBuilder.RegisterType(serviceType).As<TFrom>();

            containerBuilder.Update(_container);
        }

        /// <summary>
        /// 注册类型到容器。
        /// </summary>
        /// <typeparam name="TFrom">父类型</typeparam>
        /// <typeparam name="TTo">实现类型</typeparam>
        public void RegisterType<TFrom, TTo>()
        {
            ThrowIfNotInitialized();

            ContainerBuilder containerBuilder = new ContainerBuilder();

            containerBuilder.RegisterType<TTo>().As<TFrom>();

            containerBuilder.Update(_container);
        }

        /// <summary>
        /// 注册类型到容器，使用单例形式。
        /// </summary>
        /// <typeparam name="TFrom">父类型</typeparam>
        /// <typeparam name="TTo">实现类型</typeparam>
        public void RegisterInstance<TFrom, TTo>()
        {
            ThrowIfNotInitialized();

            ContainerBuilder containerBuilder = new ContainerBuilder();

            containerBuilder.RegisterType<TTo>().As<TFrom>().SingleInstance();

            containerBuilder.Update(_container);
        }

        // <summary>
        // 注册指定程序集的所有控制器。
        // </summary>
        // <param name="assemblies">程序集列表。</param>
        //public void RegisterControllers(params Assembly[] assemblies)
        //{
        //    ThrowIfNotInitialized();

        //    if (assemblies != null && assemblies.Length > 0)
        //    {
        //        ContainerBuilder containerBuilder = new ContainerBuilder();

        //        containerBuilder
        //            .RegisterAssemblyTypes(assemblies)
        //            .Where(t => typeof(IController).IsAssignableFrom(t) && t.Name.EndsWith("Controller", StringComparison.Ordinal));

        //        containerBuilder.Update(_container);
        //    }
        //}

        /// <summary>
        /// 注册指定程序集的所有类型。
        /// </summary>
        /// <param name="assemblies">程序集列表。</param>
        public void RegisterAssemblyTypes(params Assembly[] assemblies)
        {
            ThrowIfNotInitialized();

            if (assemblies != null && assemblies.Length > 0)
            {
                ContainerBuilder containerBuilder = new ContainerBuilder();

                containerBuilder.RegisterAssemblyTypes(assemblies);

                containerBuilder.Update(_container);
            }
        }

        /// <summary>
        /// 注册指定程序集的所有类型到它所实现的接口。
        /// </summary>
        /// <param name="assemblies">程序集列表。</param>
        public void RegisterAssemblyTypesAsImplementedInterfaces(params Assembly[] assemblies)
        {
            ThrowIfNotInitialized();

            if (assemblies != null && assemblies.Length > 0)
            {
                ContainerBuilder containerBuilder = new ContainerBuilder();

                containerBuilder.RegisterAssemblyTypes(assemblies).AsImplementedInterfaces();

                containerBuilder.Update(_container);
            }
        }

        /// <summary>
        /// 判断指定类型是否注册。
        /// </summary>
        /// <typeparam name="TSource">父类型。</typeparam>
        /// <returns></returns>
        public bool IsRegisterd<TSource>()
        {
            return this._container.IsRegistered<TSource>();
        }

        /// <summary>
        /// 判断指定类型是否注册。
        /// </summary>
        /// <param name="serviceType">类型。</param>
        public bool IsRegisterd(Type serviceType)
        {
            return this._container.IsRegistered(serviceType);
        }

        /// <summary>
        /// 从容器中取出一个 serviceType 类型的实例。
        /// </summary>
        /// <param name="serviceType">类型。</param>
        /// <returns></returns>
        public object Reslve(Type serviceType)
        {
            return this._container.Resolve(serviceType);
        }

        /// <summary>
        /// 从容器中取出一个 TService 类型的实例。
        /// </summary>
        /// <typeparam name="TService">类型。</typeparam>
        /// <returns>TService 类型的实例。</returns>
        public TService Resolve<TService>()
        {
            return this._container.Resolve<TService>();
        }

        /// <summary>
        /// 抛出未初始化异常
        /// </summary>
        private void ThrowIfNotInitialized()
        {
            if (_container == null)
                throw new InvalidOperationException("Container should be initialized before using it.");
        }
    }
}